home *** CD-ROM | disk | FTP | other *** search
- OPT PREPROCESS
-
- MODULE 'intuition/intuition',
- 'feelin','libraries/feelin','a4'
-
- -> This is the instance data for our custom class.
-
- OBJECT mydata
- x:INT,y:INT
- sx:INT,sy:INT
- ENDOBJECT
-
- PROC main()
- DEF c,w,myobj,
- fcc:PTR TO feelinClass
-
- sys_SGlob()
-
- IF feelinbase := OpenLibrary('feelin.library',FV_VERSION)
- /*
- Create the new custom class with a call to F_CreateClass().
-
- This function returns a feelinClass structure. You must use class.id to
- create instance of your custom class. This ID is unique and made by
- F_CreateClass() when ID is NIL.
- */
-
- IF fcc := F_CreateClassA([FA_SuperID, FC_Area,
- FA_DataSize, SIZEOF mydata,
- FA_Dispatcher, {myDispatcher},
- NIL])
-
- c := ClientObject,
- Child, w := WindowObject, FA_Window_Title, 'A rather complex custom class',
- Child, VGroup,
- Child, TextObject, FA_FixedHeight,TRUE, DontChain, TextFrame, TextBack, FA_Text, '`c`iPaint `nwith `bmouse`n,\n`iScroll `nwith `bcursor keys`n.', End,
- Child, myobj := F_NewObjA(fcc.id,[TextFrame, TAG_DONE]),
- End,
-
- FA_Window_ActiveObject, myobj, -> Safe here
- End,
- End
-
- IF c
- F_DoA(w,FM_Notify,[FA_Window_CloseRequest,TRUE, c,2,FM_Client_ReturnID,FV_Client_Quit])
- F_Set(w,FA_Window_Open,TRUE)
-
- F_DoA(c,FM_Client_Run,NIL)
-
- F_DisposeObj(c)
- ENDIF
-
- F_RemoveClass(fcc)
- ELSE
- WriteF('Could not create custom class.\n')
- ENDIF
-
- CloseLibrary(feelinbase)
- ELSE
- WriteF('Failed to open feelin.library\n')
- ENDIF
- ENDPROC
-
- PROC myDispatcher(cl=A2:PTR TO feelinClass,obj=A0:PTR TO feelinObject,method=D0,args=A1:PTR TO LONG)
- DEF data:PTR TO mydata
-
- sys_RGlob() ; data := INST_DATA(cl,obj)
-
- /*
- Here comes the dispatcher for our custom class. Unknown/unused methods are
- passed to the superclass immediately.
- */
-
- SELECT method
- CASE FM_AskMinMax ; mAskMinMax (cl,obj)
- CASE FM_Draw ; mDraw (cl,obj,data,args)
- CASE FM_HandleEvent ; RETURN mHandleEvent (obj,data,args)
- CASE FM_Active ; mActive (cl,obj,TRUE)
- CASE FM_Inactive ; mActive (cl,obj,FALSE)
- DEFAULT ; RETURN F_SuperDoA (cl,obj,method,args)
- ENDSELECT
- ENDPROC
- PROC mAskMinMax(cl,obj:PTR TO feelinObject)
- /*
- Area.AskMinMax() will be called before the window is opened. We need to
- tell Feelin the minimum and maximum size of our object.
-
- When you are the first receiving the method the fields _minw() and
- _minh() are set to zero and the fields _maxw() and _maxh() to FV_MAXMAX.
- We can add values to _minw() and _minh() or set _maxw() and _maxh() if
- we need to. Then we pass the method to our superclass.
-
- When the method reaches Area class these values will be adjusted
- according to FA_MinXxx, FA_FixedXxx and FA_FixXxx attributes.
- */
-
- _minw(obj) += 100 ; _minh(obj) += 40
- _maxw(obj) := 500 ; _maxh(obj) := 300
-
- F_SuperDoA(cl,obj,FM_AskMinMax,NIL)
- ENDPROC
- PROC mDraw(cl,obj:PTR TO feelinObject,data:PTR TO mydata,d:PTR TO FS_Draw)
- /*
- Draw method is called whenever Feelin feels (obviously ;-)) we should
- render our object. This usually happens after layout is finished. Note:
- You may only render within the rectangle _mleft(), _mtop(), _mwidth(),
- _mheight().
- */
-
- DEF rp
-
- /*
- Let our superclass draw itself first, Area class would e.g. draw the
- frame and clear the whole region. What it does exactly depends on flags.
- */
-
- F_SuperDoA(cl,obj,FM_Draw,d)
-
- /*
- IF FF_Draw_Object isn't set, we shouldn't draw anything. Feelin just
- wanted to update the frame or something like that.
- */
-
- rp := _rp(obj)
-
- IF d.flags AND FF_Draw_Update -> called from our input method
- IF data.sx OR data.sy
- _BPen(_pen(obj,FV_Pen_Shine))
- ScrollRaster(rp,data.sx,data.sy,_mx(obj),_my(obj),_mx2(obj),_my2(obj))
- _BPen(_pen(obj,FV_Pen_Dark))
- data.sx := NIL
- data.sy := NIL
- ELSE
- _APen(_pen(obj,FV_Pen_Shadow))
- _Plot(data.x,data.y)
- ENDIF
- ELSEIF d.flags AND FF_Draw_Object
- _APen(_pen(obj,FV_Pen_Shine))
- _Boxf(_mx(obj),_my(obj),_mx2(obj),_my2(obj))
- ENDIF
- ENDPROC
- PROC mActive(cl,obj:PTR TO feelinObject,state)
- /*
- Area class always creates an EventHandler structure in case of some
- inputmodes. As we handle events instead of Area class we can use it as
- we want. It will save us some allocations ;-)
-
- Using F_ModifyHandler() to modify IDCMP flags it's a piece of cake to
- request IDCMP events.
- */
-
- IF state
- F_DoA(obj,FM_ModifyHandler,[IDCMP_RAWKEY OR IDCMP_MOUSEBUTTONS,NIL])
- ELSE
- F_DoA(obj,FM_ModifyHandler,[NIL,IDCMP_RAWKEY OR IDCMP_MOUSEBUTTONS])
- ENDIF
-
- F_SuperDoA(cl,obj,IF state THEN FM_Active ELSE FM_Inactive,NIL)
- ENDPROC
- PROC mHandleEvent(obj:PTR TO feelinObject,data:PTR TO mydata,he:PTR TO FS_HandleEvent)
- /*
- in mSetup() we said that we want get a message if mousebuttons or keys
- pressed so we have to define the input-handler
-
- Note :
-
- This is really a good example, because it shows how to use critical
- events carefully:
-
- IDCMP_MOUSEMOVE is only needed when left-mousebutton is pressed, so we
- dont request this until we get a SELECTDOWN-message and we reject
- IDCMP_MOUSEMOVE immeditly after we get a SELECTUP-message
- */
-
- #define _between(a,x,b) (x == [a TO b])
- #define _isinobject(x,y) (_between(_mx(obj),(x),_mx2(obj)) AND _between(_my(obj),(y),_my2(obj)))
-
- /*
- Note on Arrows handling :
-
- If you don't handle arrows return NIL, this will allow Window object to
- cycle through its chain using arrows instead of tabulations (more
- confortable hu ?), else return your object. Currently, result is only check
- against NIL, but this may change in future, so return your object.
- */
-
- IF he.key <> FV_KEY_NONE
- SELECT he.key
- CASE FV_KEY_LEFT ; data.sx := -1
- CASE FV_KEY_RIGHT ; data.sx := 1
- CASE FV_KEY_UP ; data.sy := -1
- CASE FV_KEY_DOWN ; data.sy := 1
- DEFAULT ; RETURN NIL
- ENDSELECT
-
- F_Draw(obj,FF_Draw_Update)
-
- RETURN FF_HandleEvent_Eat -> Forbid arrow cycling, because *WE* handle key events.
- ELSEIF he.msg.class = IDCMP_MOUSEBUTTONS
- IF he.msg.code = SELECTDOWN
- IF _isinobject(he.msg.mousex,he.msg.mousey)
- data.x := he.msg.mousex
- data.y := he.msg.mousey
- F_Draw(obj,FF_Draw_Update)
- -> Only request IDCMP_MOUSEMOVE if we realy need it
- F_DoA(obj,FM_ModifyHandler,[IDCMP_MOUSEMOVE,NIL])
- ENDIF
- ELSE
- -> Reject IDCMP_MOUSEMOVE because lmb is no longer pressed
- F_DoA(obj,FM_ModifyHandler,[NIL,IDCMP_MOUSEMOVE])
- ENDIF
- ELSEIF he.msg.class = IDCMP_MOUSEMOVE
- IF _isinobject(he.msg.mousex,he.msg.mousey)
- data.x := he.msg.mousex
- data.y := he.msg.mousey
- F_Draw(obj,FF_Draw_Update)
- ENDIF
- ENDIF
- ENDPROC
-